/*
 * Copyright 2014, General Dynamics C4 Systems
 *
 * SPDX-License-Identifier: GPL-2.0-only
 */

#pragma once

#include <config.h>
#include <types.h>
#include <util.h>
#include <object/structures.h>
#include <arch/types.h>
#include <plat/machine/devices.h>
#include <arch/object/vcpu.h>
#include <arch/object/iospace.h>
#include <arch/object/ioport.h>
#include <plat/machine.h>

#include <mode/model/statedata.h>

/*Z 1024+1。不好：除法不会产生被舍去的余数 */
#define TSS_IO_MAP_SIZE (65536 / 8 / sizeof(word_t) + 1)
/*Z TSS段 */
typedef struct {
    tss_t   tss;                        /*Z RSP、IST项目，struct{u64[13]} */
    word_t  io_map[TSS_IO_MAP_SIZE];    /*Z I/O端口许可位图，覆盖16位端口地址空间，0-允许低权限访问，1-禁止 */
} PACKED tss_io_t;

NODE_STATE_BEGIN(archNodeState)/*Z cpu当前重要寄存器、中断状态 */ 
/* Interrupt currently being handled, not preserved across kernel entries */
NODE_STATE_DECLARE(interrupt_t, x86KScurInterrupt);/*Z 当前正处理的中断向量号 */
/* Interrupt that the hardware believes we are currently handling (is marked in service
 * in the APIC) but we have not yet gotten around to handling */
NODE_STATE_DECLARE(interrupt_t, x86KSPendingInterrupt);/*Z 当前等待处理的中断向量号。注意：最多只有一个中断pending */
/* Bitmask of all cores should receive the reschedule IPI */
NODE_STATE_DECLARE(word_t, ipiReschedulePending);/*Z 等待发出的重调度IPI目标cpu索引位图 */

#ifdef CONFIG_VTX
NODE_STATE_DECLARE(vcpu_t *, x86KSCurrentVCPU);/*Z 当前的虚拟cpu(线性地址) */
#endif

NODE_STATE_DECLARE(word_t, x86KSCurrentFSBase);/*Z 当前FS段寄存器值 */
NODE_STATE_DECLARE(word_t, x86KSCurrentGSBase);/*Z 当前GS段寄存器值 */

/* If a GP exception occurs and this is non NULL then the exception should return to
 * this location instead of faulting. In addition the GP exception will clear this
 * back to NULL */
NODE_STATE_DECLARE(word_t, x86KSGPExceptReturnTo);/*Z 用于保存期望的GP例外处理地址，GP前设置，发生后置空 */
NODE_STATE_TYPE_DECLARE(modeNodeState, mode);/*Z cpu当前CR3寄存器值 */
NODE_STATE_END(archNodeState);
/*Z TSS、GDT、IDT数据结构 */
/* this is per core state grouped into a separate struct as it needs to be available
 * at all times by the hardware, even when we are running in user mode */
typedef struct x86_arch_global_state {
    /* Task State Segment (TSS), contains currently running TCB in ESP0 */
    tss_io_t x86KStss;                      /*Z TSS段 */
    /* Global Descriptor Table (GDT) */
    gdt_entry_t x86KSgdt[GDT_ENTRIES];      /*Z GDT表。元素类型struct{u64[1]} */
    /* Interrupt Descriptor Table (IDT) */
    idt_entry_t x86KSidt[IDT_ENTRIES];      /*Z IDT表(中断向量表IVT)。元素类型struct{u64[2]} */
    PAD_TO_NEXT_CACHE_LN(sizeof(tss_io_t) + GDT_ENTRIES *sizeof(gdt_entry_t) + IDT_ENTRIES *sizeof(idt_entry_t));
} x86_arch_global_state_t;
compile_assert(x86_arch_global_state_padded, (sizeof(x86_arch_global_state_t) % L1_CACHE_LINE_SIZE) == 0)
/*Z per cpu硬件自动操作的TSS、GDT、IDT数据 */
extern x86_arch_global_state_t x86KSGlobalState[CONFIG_MAX_NUM_NODES] ALIGN(L1_CACHE_LINE_SIZE) SKIM_BSS;

extern asid_pool_t *x86KSASIDTable[];
extern uint32_t x86KScacheLineSizeBits;
extern user_fpu_state_t x86KSnullFpuState ALIGN(MIN_FPU_ALIGNMENT);

#ifdef CONFIG_IOMMU
extern uint32_t x86KSnumDrhu;/*Z ACPI提供的IOMMU数量 */
extern vtd_rte_t *x86KSvtdRootTable;
extern uint32_t x86KSnumIOPTLevels;
extern uint32_t x86KSnumIODomainIDBits;
extern uint32_t x86KSFirstValidIODomain;
#endif

#ifdef CONFIG_PRINTING
extern uint16_t x86KSconsolePort;
#endif
#ifdef CONFIG_DEBUG_BUILD
extern uint16_t x86KSdebugPort;
#endif

extern x86_irq_state_t x86KSIRQState[];

extern word_t x86KSAllocatedIOPorts[NUM_IO_PORTS / CONFIG_WORD_SIZE];
#ifdef CONFIG_KERNEL_MCS
extern uint32_t x86KStscMhz;
extern uint32_t x86KSapicRatio;
#endif

